import base64
from uuid import uuid4

from fastapi import HTTPException
from passlib.context import CryptContext

from app.model import Person, Users
from app.repository.auth_repo import JWTRepo
from app.repository.person import PersonRepository
from app.repository.users import UsersRepository
from app.schema import LoginSchema, ForgotPasswordSchema
from app.schema import RegisterSchema

# Encrypt password
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

from pathlib import Path


def get_root_relative_path(relative_path):
    script_directory = Path(__file__).resolve().parent
    while not (script_directory / "main.py").exists():
        print(script_directory)
        script_directory = script_directory.parent

    root_relative_path = script_directory / relative_path
    return root_relative_path


class AuthService:
    @staticmethod
    async def register_service(register: RegisterSchema):
        # Create uuid
        _person_id = str(uuid4())
        _users_id = str(uuid4())

        # open image profile default to bas64 string
        media_file_path = get_root_relative_path("media/profile.png")
        with open(media_file_path, "rb") as f:
            image_str = base64.b64encode(f.read())
        image_str = "data:image/png;base64," + image_str.decode("utf-8")

        # mapping request data to class entity table
        _person = Person(
            id=_person_id,
            name=register.username,  # Updated this from 'username' to 'name'
            sex=register.sex,
            profile=image_str,
            phone_number=register.phone_number,  # Updated this field
            email=register.email,  # New field
            subject_type=register.subject_type,  # New field
            exam_province=register.exam_province,  # New field
        )

        _users = Users(
            id=_users_id,
            phone_number=register.phone_number,
            password=pwd_context.hash(register.password),
            # password=register.pasfsword,
            person_id=_person_id,
        )

        # Cheking the same phone_number
        _phone_number = await UsersRepository.find_by_phone_number(
            register.phone_number
        )

        if _phone_number:
            raise HTTPException(status_code=400, detail="Phone Number already exists !")
        else:
            #  insert to tables
            await PersonRepository.create(**_person.dict())
            await UsersRepository.create(**_users.dict())

    @staticmethod
    async def logins_service(login: LoginSchema):
        _phone_number = await UsersRepository.find_by_phone_number(login.phone_number)

        if _phone_number is not None:
            # if not login.password== _phone_number.password:
            # print(login.password, _phone_number.password)
            if not pwd_context.verify(login.password, _phone_number.password):
                raise HTTPException(status_code=400, detail="Invalid Password !")
            return JWTRepo(
                data={"phone_number": _phone_number.phone_number}
            ).generate_token()
        raise HTTPException(status_code=404, detail="Phone Number not found !")

    @staticmethod
    async def forgot_password_service(forgot_password: ForgotPasswordSchema):
        _phone_number = await UsersRepository.find_by_phone_number(
            forgot_password.phone_number
        )
        if _phone_number is None:
            raise HTTPException(status_code=404, detail="Phone Number not found !")
        await UsersRepository.update_password(
            forgot_password.phone_number, pwd_context.hash(forgot_password.new_password)
        )
